﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using WpfElevator.RequisitionPart;
using AbstractFramework.LogicControl;
using WpfElevator.GlobalConstant;
using AbstractFramework;
using AbstractFramework.Constant;
using System.Windows;
using System.Windows.Controls;

namespace WpfElevator.ControlPart
{
    class Controller : IController
    {
        //public static List<int>[] elevatorEventQueue = new List<int>[SystemConstant.MAXELEVATORNUMBER]{{1,2},{3,4},{5,6}};
        //public static List<int>[] elevatorEventQueue = new List<int>[3] { { 1, 2 }, { 3, 4 }, { 5, 6 } };
        public static int ii = 20;
        //****
        public static int nextTaskNum = 0;

        public static Task[] taskList = new Task[GConstant.MAXELEVATORNUMBER];//每部电梯的任务列表
        //
        private IElevator[] elevator;//controller控制的电梯数组
        public IElevator[] _Elevator
        {
            get { return elevator; }
            set
            {
                elevator = value;
                for (int i = 0; i < elevator.Length; i++)
                {
                    taskList[i] = new Task();
                    System.Console.WriteLine("taskList[i].tasknum" + taskList[i].tasknum);
                }
            }
        }
        //private ITimer[] time;//每个电梯对应一个计时器
        //public ITimer[] _Time
        //{
        //    get { return time; }
        //    set { time = value; }
        //}

        //private long[] idleTime;//每个电梯对应一个记录空闲时间的idleTime
        //public long[] _IdleTime
        //{
        //    get { return idleTime; }
        //    set { idleTime = value; }
        //}
        //
        public void addEvent(IEvent inputevent)//此方法供外部调用，对三种不同的Event进行不同的响应
        {
            if (inputevent.eventType == EventType.fireEvent)
                addFireEvent();
            else if (inputevent.eventType == EventType.outsideEvent)//外部事件，根据选择的调度策略进行调度
            {
                if (GConstant.scheduleNo == 1)
                    addOutsideEvent(inputevent);
                else if (GConstant.scheduleNo == 2)
                    addOutsideEvent2(inputevent);
                else
                    addOutsideEvent3(inputevent);
            }
            else
                addInsideEvent(inputevent);

            Console.WriteLine("addEvent success!");
        }
        public void addFireEvent()//对fireEvent响应 
        {
           
            for (int i = 0; i < elevator.Length; i++)
            {
                int destFloor = elevator[i].Floor;
                if (elevator[i].State == MovementStatus.DownMoving)//电梯当前任务状态时向下运动，停靠在当前楼层的下一层
                {
                    destFloor--;
                }
                else if (elevator[i].State == MovementStatus.UpMoving)//当电梯状态向上运动时，停靠在当前楼层的上一层
                {
                    destFloor++;
                }
                else 
                    ;
                if (elevator[i].State != MovementStatus.Stoped)//电梯非静止状态，停靠电梯并且情况taskList
                {
                    elevator[i].moveTo(destFloor, true);
                    //elevator[i].State = MovementStatus.Stoped;//更新电梯状态为停止
                    //elevator[i].Floor = destFloor;//更新电梯停靠楼层为destFloor
                }
                else if (elevator[i].Elevator_Display.getElevatorState() == ElevatorStatus.Stoped ||
                          elevator[i].Elevator_Display.getElevatorState() == ElevatorStatus.Closing)//应该让电梯开门，然后保持不动
                {
                    elevator[i].Elevator_Display.open(true);
                }
                else
                    ;
                for (int j = 0; j < taskList[i].tasknum; j++)//清空taskList
                {
                    taskList[i].floors[j] = -1;
                    taskList[i].states[j] = -1;
                }
                taskList[i].tasknum = 0;
            }
            //将电梯外部的按钮设置为不可按状态
            //unableAllButton();
                return;
        }
        //private void unableAllButton()//用于火警按钮
        //{
        //    for (int i = 0; i < elevator.Length; i++)
        //    {
        //        Button b1 = new Button();
        //        b1.IsEnabled = false;
        //        elevator[i].InsideButtonPanel.
        //    }
        //}
        //
        public void addOutsideEvent(IEvent inputevent)//对outsideEvent响应
        {
            System.Console.WriteLine("into addOutsideEvent :inputevent.eventType=" + inputevent.eventType + "inputevent.floor= " + inputevent.floor + "inputevent.updown=" + inputevent.updown + "\r\n");
            //inputevent.requisitionFloor;inputevent.updown;inputevent.floor
            int[] reDes = new int[elevator.Length];//此数组存放每个电梯到请求楼层的相对距离
            //计算每个电梯到请求楼层 的相对距离
            System.Console.WriteLine("elevator.Length=" + elevator.Length);

            int flag = 0;

            for (int i = 0; i < elevator.Length; i++)
            {  //遍历每个电梯

                if (elevator[i].FbdFloor.Contains(inputevent.floor + 1))
                {
                    reDes[i] = int.MaxValue;
                    continue;
                }

                else
                    flag = 1;

                if (elevator[i].State == MovementStatus.Stoped)
                {
                    reDes[i] = System.Math.Abs(inputevent.floor - elevator[i].Floor);
                    continue;
                }

                int Max_floor = taskList[i].MaxFloors();
                int Min_floor = taskList[i].MinFloors();
                Max_floor = Max_floor > inputevent.floor ? Max_floor : inputevent.floor;
                Min_floor = Min_floor < inputevent.floor ? Min_floor : inputevent.floor;

                if (elevator[i].State == MovementStatus.UpMoving && inputevent.floor >= elevator[i].Floor)
                {
                    //如果电梯上行，且请求楼层高于电梯所在楼层

                    if (inputevent.updown == 1)//如果请求是向上的
                        reDes[i] = inputevent.floor - elevator[i].Floor;//距离为请求楼层-电梯楼层
                    else
                        reDes[i] = 2 * Max_floor - elevator[i].Floor - inputevent.floor;//如果请求是向下的，距离为电梯要到的最高楼层*2-请求楼层-电梯楼层
                }
                else if (elevator[i].State == MovementStatus.UpMoving && inputevent.floor < elevator[i].Floor)
                {
                    //  如果电梯上行，且请求楼层低于电梯所在楼层       
                    if (inputevent.updown == 1)//如果请求是向上的
                        reDes[i] = 2 * Max_floor - 2 * Min_floor - elevator[i].Floor + inputevent.floor;
                    else
                        reDes[i] = 2 * Max_floor - elevator[i].Floor - inputevent.floor;
                }
                else if (elevator[i].State == MovementStatus.DownMoving && inputevent.floor >= elevator[i].Floor)
                {
                    //如果电梯下行，且请求楼层高于电梯所在楼层

                    if (inputevent.updown == 1)//如果请求是向上的
                        reDes[i] = elevator[i].Floor + inputevent.floor - 2 * Min_floor;
                    else
                        reDes[i] = 2 * Max_floor - 2 * Min_floor + elevator[i].Floor - inputevent.floor;
                }
                else if (elevator[i].State == MovementStatus.DownMoving && inputevent.floor < elevator[i].Floor)
                {
                    //如果电梯下行，且请求楼层高于电梯所在楼层
                    if (inputevent.updown == 1)//如果请求是向上的
                        reDes[i] = elevator[i].Floor + inputevent.floor - 2 * Min_floor;
                    else
                        reDes[i] = elevator[i].Floor - inputevent.floor;

                }
                else
                    ;

            }
            if (flag == 0)
                return;

            for (int i = 0; i < elevator.Length; i++)
                System.Console.WriteLine("reDes[i]=" + reDes[i] + " i =" + i);
            //找出相对距离最短的电梯下标

            int tempMin = reDes.Min();
            System.Console.WriteLine("tempMin=" + tempMin);
            int tempID = -1;
            for (int i = 0; i < elevator.Length; i++)
                if (reDes[i] == tempMin)
                {
                    tempID = i;
                    break;
                }
            if (tempID == -1)
                return;
            System.Console.WriteLine("tempID=" + tempID);
            //将inputevent加入到分配的电梯的任务列表中
            this.eventIntoList(tempID, inputevent);
            //controller刷新电梯的当前任务
            this.updateTask(tempID, taskList[tempID].floors[0]);

            return;
        }
        public void addOutsideEvent2(IEvent inputevent)//对outsideEvent响应
        {
            int minDistance = 9999;//最短距离
            int key = 0;//最短距离对应的电梯号
            int floorNum = 10;//楼层数，取不到Config里面的，暂时自己设
            int temp = 0;
            int flag = 0;
            for (int i = 0; i < elevator.Length; i++)
            {

                if (elevator[i].FbdFloor.Contains(inputevent.floor + 1))
                {

                    continue;
                }
                else
                    flag = 1;

                if (elevator[i].State == MovementStatus.Stoped ||//第i个电梯静止
                   (elevator[i].State == MovementStatus.DownMoving && inputevent.updown == 0 && elevator[i].Floor > inputevent.floor) //或者请求方向与电梯运动方向均向下，且电梯楼层在请求楼层之上
                   || (elevator[i].State == MovementStatus.UpMoving && inputevent.updown == 1 && elevator[i].Floor < inputevent.floor))//或者请求方向与电梯运动方向均向上，且电梯楼层在请求楼层之下
                {
                    temp = System.Math.Abs(inputevent.floor - elevator[i].Floor);
                }
                else if ((inputevent.updown == 1 && elevator[i].State == MovementStatus.DownMoving) ||//请求向上运动，电梯向下运动
                       elevator[i].State == MovementStatus.DownMoving && inputevent.updown == 0 && inputevent.floor > elevator[i].Floor)
                {
                    temp = elevator[i].Floor + inputevent.floor;
                }
                else//请求向下运动，电梯向上运动
                {
                    temp = WpfElevator.GlobalConstant.GConstant.MAXELEVATORNUMBER - elevator[i].Floor + WpfElevator.GlobalConstant.GConstant.MAXELEVATORNUMBER - inputevent.floor;
                }
                if (minDistance > temp)
                {
                    minDistance = temp;
                    key = i;
                }
            }
            if (flag == 0)
                return;
            eventIntoList(key, inputevent);
            updateTask(key, taskList[key].floors[0]);
            return;
        }

        public void addOutsideEvent3(IEvent inputevent)//对outsideEvent响应，每台电梯中任务最少
        {
            int minTask = 9999;
            int key = 0;
            int temp = 0;
          

            for (int i = 0; i < elevator.Length; i++)
            {
                if (elevator[i].FbdFloor.Contains(inputevent.floor + 1))
                {

                    continue;
                }
                int j = 0;
                for (; taskList[i].floors[j] != 0; j++) ;
                temp = j;
                if (minTask > j)
                {
                    minTask = j;
                    key = i;
                }
            }
            if (minTask == 9999)
                return;
            eventIntoList(key, inputevent);
            updateTask(key, taskList[key].floors[0]);
            return;
        }

        //public void test()
        //{
        //    // Event e = new Event(EventType.outsideEvent, 3, 0);
        //    System.Console.WriteLine("Hello World!");
        //    return;


        //}
        public void addInsideEvent(IEvent inputevent)//对InsideEvent响应
        {
            if (elevator[inputevent.ID].FbdFloor.Contains(inputevent.requisitionFloor+1))
                return;

            this.eventIntoList(inputevent.ID, inputevent);
            updateTask(inputevent.ID, taskList[inputevent.ID].floors[0]);
            return;

        }
        public void eventIntoList(int ID, IEvent inputevent)//将inputevent加入到分配的电梯的任务列表中
        {
            //得到一个任务时，检查任务列表是否为空，若为空，说明电梯由空闲变为活跃，对电梯的空闲时间进行累加
            if (taskList[ID].tasknum == 0)
            {
                //idleTime[ID] += time[ID].end();
                SystemConstant.uniqueStatistic.updateTime(ID);
            }
            //计算每个任务中请求楼层与电梯当前位置的相对距离，以距离排序，注意此距离与请求的上下行有关，同时与电梯状态有关
            System.Console.WriteLine("ID=" + ID);
            System.Console.WriteLine("taskList[ID].tasknum=" + taskList[ID].tasknum);
            taskList[ID].tasknum++;
            //将新任务加道任务列表尾部

            if (inputevent.eventType == EventType.outsideEvent)
            {
                taskList[ID].floors[taskList[ID].tasknum - 1] = inputevent.floor;
                taskList[ID].states[taskList[ID].tasknum - 1] = inputevent.updown;
            }
            else if (inputevent.eventType == EventType.insideEvent)
            {
                taskList[ID].floors[taskList[ID].tasknum - 1] = inputevent.requisitionFloor;
                taskList[ID].states[taskList[ID].tasknum - 1] = 2;
            }

            int[] reDes = this.sortTaskList(ID);
            this.updateRavTime(reDes, ID);


            return;
        }
        public int[] sortTaskList(int ID)//计算每个任务到电梯ID的相对距离，存于reDes，将taskList按reDes排序，返回taskList 相对应的相对距离数组reDes
        {

            int[] reDes = new int[taskList[ID].tasknum];//此数组存放每个请求楼层到电梯的相对距离



            int Max_floor = taskList[ID].MaxFloors();
            int Min_floor = taskList[ID].MinFloors();


            //计算reDes[]
            int n = taskList[ID].tasknum;
            for (int i = 0; i < n; i++)
            {  //遍历每个任务

                if (elevator[ID].State == MovementStatus.Stoped)
                {
                    reDes[i] = System.Math.Abs(taskList[ID].floors[i] - elevator[ID].Floor);
                    continue;
                }

                if (elevator[ID].State == MovementStatus.UpMoving && taskList[ID].floors[i] >= elevator[ID].Floor)
                {//如果电梯上行，且请求楼层高于电梯所在楼层

                    if (taskList[ID].states[i] == 1 || taskList[ID].states[i] == 2)//如果请求是向上的,或是内部的
                        reDes[i] = taskList[ID].floors[i] - elevator[ID].Floor;//距离为请求楼层-电梯楼层
                    else
                        reDes[i] = 2 * Max_floor - elevator[ID].Floor - taskList[ID].floors[i];//如果请求是向下的，距离为电梯要到的最高楼层*2-请求楼层-电梯楼层
                }
                else if (elevator[ID].State == MovementStatus.UpMoving && taskList[ID].floors[i] < elevator[ID].Floor)
                {
                    //  如果电梯上行，且请求楼层低于电梯所在楼层       
                    if (taskList[ID].states[i] == 1)//如果请求是向上的
                        reDes[i] = 2 * Max_floor - 2 * Min_floor - elevator[ID].Floor + taskList[ID].floors[i];
                    else
                        reDes[i] = 2 * Max_floor - elevator[i].Floor - taskList[ID].floors[i];
                }
                else if (elevator[ID].State == MovementStatus.DownMoving && taskList[ID].floors[i] >= elevator[ID].Floor)
                {
                    //如果电梯下行，且请求楼层高于电梯所在楼层

                    if (taskList[ID].states[i] == 1)//如果请求是向上的,或是内部的
                        reDes[i] = elevator[ID].Floor + taskList[ID].floors[i] - 2 * Min_floor;
                    else
                        reDes[i] = 2 * Max_floor - 2 * Min_floor + elevator[ID].Floor - taskList[ID].floors[i];
                }
                else if (elevator[ID].State == MovementStatus.DownMoving && taskList[ID].floors[i] < elevator[ID].Floor)
                {
                    //如果电梯下行，且请求楼层低于电梯所在楼层
                    if (taskList[ID].states[i] == 1)//如果请求是向上的
                        reDes[i] = elevator[ID].Floor + taskList[ID].floors[i] - 2 * Min_floor;
                    else
                        reDes[i] = elevator[ID].Floor - taskList[ID].floors[i];

                }
                else
                    ;

            }
            //以reDes将task排序
            Array.Sort(reDes, taskList[ID].floors, 0, taskList[ID].tasknum);
            Array.Sort(reDes, taskList[ID].states, 0, taskList[ID].tasknum);
            for (int i = 0; i < taskList[ID].tasknum; i++)
            {
                System.Console.WriteLine("reDes[i]=" + reDes[i] + " i =" + i);
                System.Console.WriteLine("taskList[ID].floors[i]=" + taskList[ID].floors[i] + " i =" + i);
                System.Console.WriteLine("taskList[ID].states.[i]=" + taskList[ID].states[i] + " i =" + i);


            }
            return reDes;

        }
        public void updateRavTime(int[] reDes, int ID)//计算并刷新电梯ID各层请求的预计到达时间
        {
            int n = taskList[ID].tasknum;
            int tempTime = 0;

            for (int i = 0; i < n; i++)
            {
                if (taskList[ID].states[i] != 2)
                {
                    tempTime = reDes[i] * GConstant.RUNTIME + i * GConstant.STAYTIME;
                    string timeMessage = tempTime.ToString() + " s";
                    System.Console.WriteLine("tempTime" + tempTime + " i =" + i);
                    string elevatorName = "电梯" + ID;
                    if(taskList[ID].states[i] == 0)
                        elevator[ID].DownFloor_Indicator[taskList[ID].floors[i]].showMessage(elevatorName, timeMessage);
                    else
                        elevator[ID].UpFloor_Indicator[taskList[ID].floors[i]].showMessage(elevatorName, timeMessage);
                }

            }


        }
        public void updateTask(int ID, int desFloor)//controller刷新电梯的当前任务
        {
            ////判断如果当前响应的是外部请求，则向desFloor楼层的指示器发送响应消息
            //if(taskList[ID].states[0] != 2)//外部请求
            //{
            //    string elevatorName = "电梯"+ID;
            //    string responseTime = "10s";//需要修改的！！！！！！
            //    elevator[ID].DownFloor_Indicator[desFloor].showMessage(elevatorName, responseTime);
            //}

            ///
            ///加些判断电梯当前状态的条件判断语句
            ///
            elevator[ID].moveTo(desFloor, true);
        }
        public void nextTask(int ID)//供elevator调用，取下一个任务
        {
            nextTaskNum++;
            if (taskList[ID].states[0] == -1)
                return;
            //先将产生队首任务的按钮等的状态进行修改，即熄灭按钮
            switch (taskList[ID].states[0])
            {
                case 0: //外部向下
                    elevator[ID].OutsideButtonPanel[taskList[ID].floors[0]].extinguish(1);//1：表示熄灭向下的灯
                    elevator[ID].DownFloor_Indicator[taskList[ID].floors[0]].showMessage("", ""); //清除外部楼层指示器的信息
                    break;
                case 1://外部向上
                    elevator[ID].OutsideButtonPanel[taskList[ID].floors[0]].extinguish(0);//0：表示熄灭向上的灯
                    elevator[ID].UpFloor_Indicator[taskList[ID].floors[0]].showMessage("", "");//清除外部楼层指示器的信息
                    break;
                case 2://内部按钮
                    elevator[ID].InsideButtonPanel.extinguish(taskList[ID].floors[0]);
                    break;
                default:
                    MessageBox.Show("taskList中按钮类型错误", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                    break;
            }
            taskList[ID].floors[0] = -1;
            taskList[ID].states[0] = -1;
            for (int i = 1; i<taskList[ID].tasknum; i++)
            {
                taskList[ID].floors[i - 1] = taskList[ID].floors[i];
                taskList[ID].states[i - 1] = taskList[ID].states[i];
            }
            taskList[ID].floors[taskList[ID].tasknum - 1] = -1;//最后一个任务的位置设置为初始值-1
            taskList[ID].states[taskList[ID].tasknum - 1] = -1;

            taskList[ID].tasknum--;

            //从任务列表中减去一个任务之后，检查此时任务数是否为0，若为0，说明电梯要空闲了，建立空闲时间
            if (taskList[ID].tasknum == 0)
            {
                //time[ID].creatTimer();
                SystemConstant.uniqueStatistic.time[ID].creatTimer();
            }

            Console.WriteLine("taskList[{0}].tasknum = {1}", ID, taskList[ID].tasknum);
            if (taskList[ID].tasknum > 0)
            {
                updateTask(ID, taskList[ID].floors[0]);
                for (int i = 0; i < taskList[ID].tasknum; i++ )
                {
                    Console.WriteLine("taskList[{0}].taskNo = {1}", ID, i);
                    Console.WriteLine("\ttaskList[{0}].floors[{1}] = {2}", ID,i, taskList[ID].floors[i]);
                    Console.WriteLine("\ttaskList[{0}].states[{1}]= {2}", ID, i,taskList[ID].states[i]);
                }
            }

            int[] reDes = this.sortTaskList(ID);
            this.updateRavTime(reDes, ID);
            return;    
        }
    }
}
